
import pandas as pd
import logging
from tqdm import tqdm

mylog = logging.getLogger()

class ExcelConcat():
    def __init__(self,sheet_columns_df):
        self._scd = sheet_columns_df
        if self._scd.empty:
            raise ValueError("Excel 使用的列名数据表为空！")
        
    def _getUsedSheet(self):
        '''从使用列名配置表中获取所有用到的sheet表信息。
        '''
        sheet_path_df = self._scd.loc[:,['文件编号','文件路径','年度','Sheet表名','列名行位置']]
        return sheet_path_df.drop_duplicates()

    
    def concat(self):
        '''将结构一致或近似的一组Excel文件合并为一个表数据。
        1.使用get_all_excel_struct获取指定目录下所有Excel文件的结构。
        2.使用out_excel_path_struct输出Excel文件结构为xlsx文件，进行配置。
        3.使用get_excel_path_struct获取配置后实际使用的Excel文件结构。
        4.使用analysis_excels获取指定文件结构的Execel文件信息。
        5.使用out_excels_columns_config将这一组文件中的列名结构以及列名分析输出为Excel文件，用于手动处理。
            （1）.使用get_excels_columns获取这一组文件中的列名结构以及列名分析。
            （2）.使用xlsxwriterformat将结果写入“当前处理Excel文件标题配置.xlsx”中，可指定写入路径。
        6.手动编辑“当前处理Excel文件标题配置.xlsx”文件，配置使用到的列及列名别名，列名对应列的数据类型。
        7.调用get_exels_columns_config获取配置后所有使用到的列的详细信息。
        5.调用此文件组合这一组Excel数据。
        '''
    
        #构造新生成的列
        all_new_columns = ['文件编号','年度']
        for index,line in self._scd.iterrows():
            column_name = line['列名']
            need_map = line['使用别名']
            map_column = line['列名的别名']
            if need_map in ['是','Y',True,'TRUE','True']:
                if not pd.isna(map_column):
                    all_new_columns.append(map_column)
                    continue
            all_new_columns.append(column_name)
        #print(all_new_columns,type(all_new_columns))
        all_new_columns = pd.unique(pd.Series(all_new_columns))
        all_df = pd.DataFrame(columns=all_new_columns)
    
        #迭代生成每个要读取的表
        #使用通过analysis_excels分析被处理表得到的excel文件基本信息提取所有用到的文件路径及Sheet表名。如果使用使用
        #excels_used_columns获取用到的所有Excel文件路径及Sheet表名，则需要进行运算。
        used_sheet_df = self._getUsedSheet()
        with tqdm(total=len(used_sheet_df)) as pbar:
            count = 0
            for index in used_sheet_df.index.values:
                count += 1
                pbar.set_description("文件合并进度")
                pbar.update(1)
                line = used_sheet_df.loc[index]
            #for _,line in used_sheet_df.iterrows():
                file_id = line['文件编号']                      #要处理的文件编号
                file_path = line['文件路径']                    #要处理的文件路径
                file_sheet = line['Sheet表名']                  #要处理的文件Sheet名称
                file_year = line['年度']
                header_index = line['列名行位置']                 #列名所在位置
                mylog.debug("正在读取{}/{}数据表。。".format(file_path,file_sheet))

                one_sheet_df = self._scd.loc[self._scd['文件编号']==file_id]
                #orignal_columns = []
                mapped_columns = []
                #column_types = []
                used_columns = []
                used_column_count = 0
                data_types = dict()
                for _,column_line in one_sheet_df.iterrows():
                    #orignal_columns.append(column_line['列名'])
                    used_columns.append(column_line['列名列位置'])
                    map_item = column_line['使用别名']
                    if map_item in ['是','Y',True,'TRUE','True'] and not pd.isna(column_line['列名的别名']):
                        mapped_columns.append(column_line['列名的别名'])
                    else:
                        mapped_columns.append(column_line['列名'])
                    data_type = column_line['列数据类型']
                    if pd.isna(data_type) or data_type not in ['object','str','int','float','int64','datetime64[ns]','float64']:
                        #column_types.append('object')
                        result_data_type = 'object'
                    else:
                        #column_types.append(data_type)
                        result_data_type = data_type
                    data_types[used_column_count] = result_data_type
                    used_column_count += 1
                #data_type = {key:value for key,value in zip(used_columns,column_types)}
                #mylog.debug("used_columns:{}".format(used_columns))
                #mylog.debug("mapped_columns:{}".format(mapped_columns))
                #mylog.debug("column_types:{}".format(column_types))
                #mylog.debug("data_type:{}".format(data_types))
                data = pd.read_excel(file_path,sheet_name=str(file_sheet),header=header_index,usecols=used_columns,dtype=data_types)
                #考虑到合并的时候，可能存在两张表中的同一列位置不同的情况，使用之前统一的顺序放置，避免位置不对齐
                data.columns = mapped_columns
                temp_list = []
                for item in all_new_columns:
                    if item in mapped_columns:
                        temp_list.append(item)
                data = data.loc[:,temp_list]
                data.insert(0,'文件编号',file_id)
                data.insert(1,'年度',file_year)
                if not all_df.empty and not data.empty:
                    try:
                        all_df = pd.concat([all_df,data],ignore_index=True)
                    except Exception as e:
                        print("连接产生异常：")
                        print("trace:",e)
                        import pickle
                        with open("all_df_data.pickle","wb") as ad:
                            pickle.dump(all_df,ad)
                        with open("data.pickle","wb") as dt:
                            pickle.dump(data,dt)
                        print("all_df:",all_df)
                        print("data:",data)
                elif not data.empty:
                    all_df = data.copy()
                else:
                    all_df = all_df
        return all_df